home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
326-350
/
disk_349
/
med
/
source
/
med200src.zoo
/
med-player.a
< prev
next >
Wrap
Text File
|
1990-04-03
|
28KB
|
1,018 lines
; MED - by Teijo Kinnunen, 1989, 1990
; med-player.a - the player routine
custom EQU $dff000
dmacon EQU $096
aud0 EQU $0A0
aud1 EQU $0B0
aud2 EQU $0C0
aud3 EQU $0D0
ac_ptr EQU $00
ac_len EQU $04
ac_per EQU $06
ac_vol EQU $08
xdef _GetSerial
xdef _FreeSerial
xdef _AddMIDIData
xdef _AudioInit
xdef _AudioRem
xdef _ChannelOff
xdef _SetTempo
xref _tamakappale
xref _PiirraPylvas
xref _soitin
xref _aanipaalla
xref _zeroptr
xref _periodit
xref _specialupd
xref _counter
xref DrawEqualizer
section "text",code
EVEN
dc.b ' MEDPlayer is here!!!:'
waithwnum: dc.l 500
newaptr: dc.l 0,0,0,0
newalen: dc.w 0,0,0,0
audaddr: dc.l custom+aud0,custom+aud1,custom+aud2,custom+aud3
_ChannelOff: ;d0 = channel #
lea prevmidinote,a0 ;first: is it MIDI??
move.b 0(a0,d0.w),d1
beq.s notcomidi ;not midi note
clr.b 0(a0,d0.w)
clr.l noteondata ; new midi msg
move.b d1,noteondata+1
lea prevmidichan,a0
move.b 0(a0,d0.w),noteondata ;prev midi channel
or.b #$80,noteondata ;note off
lea noteondata,a0
moveq.l #3,d0
bra.w _AddMIDIData
notcomidi: cmp.b #4,d0
bge.s notamigatrk
moveq.l #1,d1
lsl.w d0,d1
move.w d1,$dff096
notamigatrk: rts
_SoitaNuotti: ;d0 = trk #, d1 = note #, d2 = vol, d3 = instr #
movem.l a2-a3/d3-d7,-(sp) ;All right, let's start!!
move.w d2,-(sp)
clr.l d4
bset d0,d4 ;d4 is mask for this channel
lea _soitin,a0 ;Is this instrument in mem?
lsl.w #2,d3 ;d3 = instr.num << 2
tst.l 0(a0,d3.w)
bne.s inmem
lsr.w #2,d3
lea _tamakappale+1574,a0
tst.b 0(a0,d3.w) ;is MIDI channel set
beq.w retsn2 ; NO!!!
lsl.w #2,d3
inmem: lsr.w #1,d3 ;d3 = instr. num << 1
lea _aanipaalla,a0 ;Is this track on??
lsl.w #1,d0 ;d0 = track num << 1
tst.w 0(a0,d0.w)
beq.w retsn2 ; NO!!!!!!
lsr.w #1,d0
add.b _tamakappale+1550,d1 ;add play transpose
bgt.s notenot2low
add.b #12,d1 ;note was too low, octave up
bra.s endpttest
notenot2low: cmp.b #63,d1
ble.s endpttest
sub.b #12,d1 ;note was too high, octave down
endpttest: jsr DrawEqualizer(pc)
cmp.b #4,d0
bge.s nodmaoff ;track # >= 4: not an Amiga channel
move.w d4,$dff096 ;stop this channel (dmacon)
nodmaoff: lea prevmidinote,a0
move.b 0(a0,d0.w),d6 ;get prev. midi note
beq.s noprevmidi
clr.b 0(a0,d0.w)
move.b d6,noteondata+1
lea prevmidichan,a0
move.b 0(a0,d0.w),noteondata ;prev midi channel
or.b #$80,noteondata ;note off
lea noteondata,a0
clr.b 2(a0) ;clear volume
movem.l d0-d1,-(sp)
moveq.l #3,d0
bsr.w _AddMIDIData
movem.l (sp)+,d0-d1
noprevmidi: lea _tamakappale+1574,a1
lsr.w #1,d3
tst.b 0(a1,d3.w)
bne.w handleMIDInote
cmp.b #4,d0 ;test track # again
bge.w retsn2 ;no Amiga instruments in tracks > 3
or.w d4,dmaonmsk
subq.b #1,d1
lsl.w #1,d0
lsl.w #1,d3
lea newalen(pc),a2
clr.w 0(a2,d0.w)
move.w d0,d6
lsl.w #1,d6 ;d6 = channel num << 2
move.w d3,d7
lsl.w #1,d7 ;d7 = instr. num << 2
lea audaddr,a1
movea.l 0(a1,d6.w),a1 ;base of this channel's regs
lea newaptr(pc),a3 ;a3 = address of newaptr
lea _soitin,a2 ;get the address of...
move.l 0(a2,d7.w),d5 ;...this instrument
move.l d5,a0
bsr.w getinsdata
move.l d0,ac_ptr(a1) ;put it in ac_ptr
cmp.w #2,d3
bls.s norepeat
add.l d2,d0 ;d0 = starting address of repeat
move.l d0,0(a3,d6.w) ;remember!! (move to newaptr)
lsr.w #1,d3 ;shift right
lsr.w #1,d6
move.w d3,16(a3,d6.w) ;remember too (newalen)
lsr.w #1,d2 ;shift
beq.s begin0 ;rep. start < 2
move.w d2,ac_len(a1) ;move repeat to hardware
bra.s retsn1
begin0: move.w d3,ac_len(a1)
bra.s retsn1
norepeat: move.l _zeroptr,0(a3,d6.w) ;pointer of zero word
lea newalen(pc),a3
lsr.w #1,d6
move.w #1,0(a3,d6.w) ;length: 1 word
lsr.l #1,d1 ;shift length right
move.w d1,ac_len(a1) ;and put to custom chip
retsn1: move.w d5,ac_per(a1) ;getinsdata puts period to d5
lea prevper(pc),a0
move.w d5,0(a0,d6.w)
move.w (sp),ac_vol(a1) ;volume
lsr.w #2,d7 ;d7 is now instr. number again
drawcol: move.w d7,d0 ;to d0
subq.w #1,d0 ;number of column
clr.l d1
move.w (sp),d1 ;volume (height) to d1
lsr.b #1,d1 ;to range 0 - 32
and.b #$fe,d1 ;must be even
beq.s nodraw ;volume = 1, don't draw
jsr _PiirraPylvas(pc) ;draw it
nodraw: move.b _tamakappale+1551,d0 ;flags
btst #1,d0 ;jumping ??
beq.s retsn2 ;no...
btst #2,d0 ;with instruments
bne.s retsn2 ;no......
move.l _tamakappale+1554,d0 ;yes!!!, get instr. mask
lsr.l d7,d0 ;set this instr. to bit #0
btst #0,d0 ;and test it
beq.s retsn2 ;no jump with this instr
move.b #1,animcnt ;init animation counter
retsn2: addq.l #2,sp ;forget volume
movem.l (sp)+,a2-a3/d3-d7
rts
handleMIDInote:
add.b #23,d1 ;2 octaves higher and -1
move.b d1,noteondata+1 ;MIDI msg note #
lea prevmidinote(pc),a0
move.b d1,0(a0,d0.w) ;save this note number
move.b d2,d4 ;temporary save the volume
subq.b #1,d2 ;if 64 => 63
lsl.b #1,d2 ;volume 0 - 63 => 0 - 127
bclr #7,d2 ;be sure that bit 7 is clear
move.b d2,noteondata+2 ;MIDI msg volume
clr.w d1
move.b 0(a1,d3.w),d1 ;get midi chan of this instrument
subq.b #1,d1 ;from 1-16 to 0-15
lea prevmidichan(pc),a0
move.b d1,0(a0,d0.w) ;save to prev midi channel
move.b #$90,noteondata ;MIDI: Note on
or.b d1,noteondata ;MIDI msg Note on & channel
move.b 32(a1,d3.w),d2 ;get preset #
beq.s nochgpres ;zero = no preset
lea prevmchpreset(pc),a0
move.b 0(a0,d1.w),d0
cmp.b d2,d0 ;is this previous preset ??
beq.s nochgpres ;yes...no need to change
move.b #$c0,preschgdata
or.b d1,preschgdata
move.b d2,0(a0,d1.w) ;save preset to prevmchpreset
subq.b #1,d2
move.b d2,preschgdata+1
lea preschgdata,a0
moveq.l #5,d0
bra.s preschanged
nochgpres: moveq.l #3,d0
lea noteondata,a0
preschanged: bsr.w _AddMIDIData
move.w d3,d7
bra.w drawcol
_StartDMA: ;This small routine turns on audio DMA
move.w dmaonmsk,d0 ;dmaonmsk contains the mask of
beq.s retsdma ;the channels that must be turned on
bset #15,d0 ;DMAF_SETCLR: set these bits in dmacon
move.l waithwnum,d1
waithw0: dbf d1,waithw0
move.w d0,custom+dmacon ;do that!!!
move.l waithwnum,d1
waithw1: dbf d1,waithw1
lsr.b #1,d0 ;finally, push new ptrs to audio hw regs
bcc.s pushch1
move.l newaptr(pc),custom+aud0+ac_ptr
move.w newalen(pc),custom+aud0+ac_len
pushch1: lsr.b #1,d0
bcc.s pushch2
move.l newaptr+4(pc),custom+aud1+ac_ptr
move.w newalen+2(pc),custom+aud1+ac_len
pushch2: lsr.b #1,d0
bcc.s pushch3
move.l newaptr+8(pc),custom+aud2+ac_ptr
move.w newalen+4(pc),custom+aud2+ac_len
pushch3: lsr.b #1,d0
bcc.s retsdma
move.l newaptr+12(pc),custom+aud3+ac_ptr
move.w newalen+6(pc),custom+aud3+ac_len
retsdma: rts
xref _mouse1
xref _mouse2
xref _mouse3
xref _mouse4
xref _mouse5
frame: dc.l 0,_mouse2,_mouse3,_mouse4,_mouse5,_mouse5,_mouse4,_mouse3
dc.l _mouse2,_mouse1,0
dmaonmsk: dc.w 0
animcnt: dc.b 0,0
prevmidinote: dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
prevmidichan: dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
prevpitchbend: dc.w $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
dc.w $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
prevmchpreset: dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;previous preset
prevper: dc.w 0,0,0,0
prevnote: dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
previnstr: dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
prevvol: dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
effect: dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
effectqual: dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
nextblock: dc.b 0
animpause: dc.b 1
numtracks: dc.b 0,0
xref _soittotila
xref _soittolohko
xref _lohko
xref _soittorivi
xref _soittolohkonnum
xref _lohkoja
xref _naytonpaivitys
xref _maintsk
xref _nayttomsk
xref _tempo
xref _sprptr
xref _hyppymsk
xref _komento
_IntHandler:
movem.l d2-d7/a2-a4,-(sp)
cmp.w #5,_komento ;Do we have to play note from keyboard
bne.s nokbnote ;no...just normal playing
lea _komento,a1 ;get the address of the structure
lea _tamakappale+1284,a2 ;and the song
clr.w dmaonmsk
clr.w d0
clr.w d1
move.b 8(a1),d0 ;get all these values from
move.b 5(a1),d1 ;the command structure
move.w 6(a1),d3
clr.w d2
move.b 0(a2,d3.w),d2
clr.w (a1) ;clear the command word
bsr _SoitaNuotti ;and play the note finally
bsr _StartDMA
bra.s notplaying ;exit
nokbnote: tst.w _soittotila ;are we playing
bne.s playing ;yes, we are
bclr.b #0,$bfee01 ;no...stop the timer
move.b #$05,_counter
clr.b animcnt
move.l frame+36,_sprptr
bra.w sigjump
notplaying: movem.l (sp)+,d2-d7/a2-a4 ;exit interrupt
rts
playing: clr.w dmaonmsk
add.b #1,_counter
cmp.b #6,_counter ;if counter = 6: new note and fx
bne.w nonewnote ;if counter is not 6: just do fx
clr.b _counter ;new note!!!
clr.l d7 ;number of track
lea _lohko,a2 ;a2 = address of 1st block's address
move.w _soittolohko,d2
lsl.w #2,d2 ;shift to longword index
movea.l 0(a2,d2.w),a2 ;get the pointer of the block
move.b (a2),numtracks+1 ;save # of tracks
addq.l #4,a2 ;skip...
move.w numtracks,d3
mulu #3,d3
move.w _soittorivi,d2
mulu d2,d3
adda.l d3,a2 ;a2 = address of this line
lea prevnote(pc),a3
lea _tamakappale,a4
trloop0: clr.w d5
move.b (a2)+,d5 ;get the number of this note
move.b (a2)+,d6 ;and the 4 numbers containing fx
lsl.w #8,d6
move.b (a2)+,d6
lea effectqual(pc),a1
move.b d6,0(a1,d7.w) ;save the fx numbers
clr.b d4 ;d4 is a flag: if set, instr. is
btst #7,d5 ;in range G-V. If clr, it's 1-F.
beq.s nogtov ;In the song, if bit #7 is set in
bclr #7,d5 ;note number byte, it's G-V
st.b d4 ;this instrument is in range G-V
nogtov: move.w #$f000,d0
and.w d6,d0 ;d0 now contains only the # of instr
bne.s instnum ;instrument number is not 0
tst.b d4 ;maybe it's G (instr. #0, d4 set)
beq.s noinstnum ;no. It's 0!!!
instnum: lsr.w #8,d0 ;shift it right to get number 0-F
lsr.b #4,d0
tst.b d4
beq.s nogtov2
add.w #16,d0 ;if G-V, add 16 to the number
nogtov2: lea previnstr(pc),a1
move.b d0,0(a1,d7.w) ;remember instr. number!
lea prevvol(pc),a1
add.w #1284,d0 ;offset of volumes in song struct
move.b 0(a4,d0.w),0(a1,d7.w) ;vol of this instr to prevvol
noinstnum: move.w d6,d0 ;effect again...
lsr.w #8,d0
and.b #$0f,d0 ;now check only the effect part
lea effect(pc),a1
move.b d0,0(a1,d7.w) ;save the effect number
beq.s noeffect ;no effect
cmp.b #$0f,d0 ;yes effect...is it Tempo???
bne.s not0f ;not Tempo
tst.b d6 ;Tempo !!!
beq.s fx0fchgblck ;if effect qualifier (last 2 #'s)..
cmp.b #$f0,d6 ;..is zero, go to next block
bhi.s fx0fspecial ;if it's F1-FF something special
clr.l d0 ;will happen!!!
move.b d6,d0
bsr _SetTempo ;change The Tempo
bra.s noeffect
fx0fspecial: cmp.b #$f2,d6 ; | rest - play | SpecialFX#2: no note..yet
bne.s isfxfe ;not SpecFX2
move.b d5,(a3) ;Yes!!! Save the note number
clr.w d5 ; clear the number for awhile
bra.s noeffect
isfxfe: cmp.b #$fe,d6
bne.s noeffect
clr.w _soittotila
or.b #2,_specialupd
bra.s noeffect
fx0fchgblck: st.b nextblock ;next block????...YES!!!! (F00)
bra.s noeffect
not0f: cmp.b #$0c,d0 ;new volume???
bne.s noeffect ;NO!!!!!!!!!!!!!!!!!!!!!!
move.b d6,d0
lsr.b #4,d0 ;Strange code begins now
mulu #10,d0
move.b d6,d1
and.b #$0f,d1
add.b d1,d0 ;strange code ends now: d0 is vol
cmp.b #64,d0
bls.s novolov64
moveq.l #64,d0
novolov64 lea prevvol(pc),a1
move.b d0,0(a1,d7.w) ;and save it....
noeffect: tst.b d5 ;Now we'll check if we have to play a note
beq.s endtrkloop ;no.
move.b d5,(a3)
move.w d7,d0
move.w d5,d1
clr.w d2
clr.w d3
lea previnstr(pc),a1
move.b 0(a1,d7.w),d3
lea prevvol(pc),a1
move.b 0(a1,d7.w),d2 ;get volume
bsr _SoitaNuotti ;play it!!!!!!!!!!!
endtrkloop: addq.l #1,a3 ;a3 = pointer to prev. note #
addq.l #1,d7
cmp.w numtracks,d7
blt.w trloop0
add.w #1,_soittorivi ;very important!!! advance line!!
cmp.w #63,_soittorivi ;important too!!! advance block??
bgt.s chgblock ;yes!!!
tst.b nextblock ;command F00 ??
beq.s nochgblock ;no, don't change block
chgblock: clr.w _soittorivi ;clear line number
cmp.w #2,_soittotila ;play block or play song
bne.s nonewseq ;play block only...
add.w #1,_soittolohkonnum ;advance sequence number
move.w 1546(a4),d0 ;get the highest seq number
move.w _soittolohkonnum,d1 ;and current seq number
cmp.w d0,d1 ;is this the highest seq number
blt.s nostartagain ;no
clr.w _soittolohkonnum ;yes: play song again
clr.w d1 ;...forever!!!
nostartagain: clr.w d0
lea 1446(a4),a1 ;offset of sequence table
move.b 0(a1,d1.w),d0 ;get number of the block
move.w d0,_soittolohko ;and put it to block number var
move.w _lohkoja,d1 ;get number of blocks
subq.w #1,d1 ;# of blocks-1 = # of highest block
cmp.w d1,d0 ;is this block number too big
blt.s nonewseq ;no
move.w d1,_soittolohko ;yes..then play just the last block
nonewseq: clr.b nextblock ;clear this if F00 set it
nochgblock: tst.w _naytonpaivitys ;screen updating on??
beq.s nonewnote ;no
movea.l _maintsk,a1 ;ask the main task to update screen
move.l _nayttomsk,d0
jsr -$144(a6) ;Signal()
nonewnote:
; *********************** This code produces the effects **
clr.l d7 ;clear track count
lea prevper(pc),a3
lea prevvol(pc),a4
trloop1: clr.w d5
lea effect,a1
clr.w d4
move.b 0(a1,d7.w),d6 ;get the fx number
lea effectqual,a1
move.b 0(a1,d7.w),d4 ;and the last 2 #'s
lea prevmidinote,a0 ;first: is it MIDI??
tst.b 0(a0,d7.w)
bne.w midifx
cmp.b #1,d6 ;effect #1
bne.s nofx01
; **************************************** Effect 01 ******
cmp.w #5,_tamakappale+1552
bne.s nost1
tst.b _counter
beq newvals
nost1: sub.w d4,(a3) ;slide it up!!!
cmp.w #113,(a3) ;too high???
bge newvals
move.w #113,(a3) ;yes, too high!!!
bra newvals
; *********************************************************
nofx01: cmp.b #2,d6
bne.s nofx02
; **************************************** Effect 02 ******
cmp.w #5,_tamakappale+1552
bne.s nost2
tst.b _counter
beq newvals
nost2: add.w d4,(a3) ;slide it down!!!!!!!!!
cmp.w #856,(a3) ;too low??
ble newvals
move.w #856,(a3) ;too low.
bra newvals
; *********************************************************
nofx02: tst.b d6
bne.s nofx00
; **************************************** Effect 00 ******
tst.b d4 ;both fxqualifiers are 0s: no arpeggio!!
beq.w endl
lea prevnote,a1
bsr.w DoArpeggio
subq.b #1,d4 ;-1 to make it 0 - 127
add.b _tamakappale+1550,d4 ;add play transpose
lsl.b #1,d4 ;shift to make index for UWORD
lea _periodit,a1
move.w 0(a1,d4.w),d5
bra.w newvals
; *********************************************************
nofx00: cmp.b #$0d,d6
bne.s nofx0d
; **************************************** Effect 0D ******
move.b d4,d1
move.b (a4),d0 ;move previous vol to d0
and.b #$f0,d1
bne.s crescendo
sub.b d4,d0 ;sub from prev. vol
bpl.s novolund0
clr.b d0 ;volumes under zero not accepted!!!
novolund0: move.b d0,(a4) ;put new vol back
bra newvals
crescendo: lsr.b #4,d1
add.b d1,d0
cmp.b #64,d0
ble.s novolover64
moveq.l #64,d0
novolover64: move.b d0,(a4)
bra newvals
; *********************************************************
nofx0d: cmp.b #3,d6
bne.s nofx03
; **************************************** Effect 03 ******
move.w (a3),d5 ;this is very simple: get the old period
cmp.b #3,_counter ;and..
bge.w newvals ;if counter < 3
sub.w d4,d5 ;subtract effect qualifier
bra.w newvals
; *********************************************************
nofx03: cmp.b #$0f,d6
bne.s nofx0f
; **************************************** Effect 0F ******
fx0f: cmp.b #$ff,d4
bne.s no0fff
move.w d7,d0
bsr.w _ChannelOff
bra.w endl
no0fff: cmp.b #$f1,d4
bne.s no0ff1
cmp.b #3,_counter
bne.s newvals
bra.s playfxnote
no0ff1: cmp.b #$f2,d4
bne.s no0ff2
cmp.b #3,_counter
bne.s newvals
bra.s playfxnote
no0ff2: cmp.b #$f3,d4
bne.s endl
move.b _counter,d0
and.b #2+4,d0 ;is 2 or 4
beq.s newvals
playfxnote: move.w d7,d0 ;track # to d0...
lea prevnote(pc),a1
clr.w d1
move.b 0(a1,d7.w),d1 ;get note # of previous note
clr.w d2
move.b (a4),d2 ;get previous volume
lea previnstr(pc),a1
clr.w d3
move.b 0(a1,d7.w),d3
bsr _SoitaNuotti
bra.s endl
; *********************************************************
nofx0f: cmp.b #$0e,d6
bne.s nofx0e
fx0e: or.b #1,_specialupd
tst.b d4
bne.s filteroff
bclr #1,$bfe001
bra.s endl
filteroff: bset #1,$bfe001
bra.s endl
nofx0e: cmp.b #$0c,d6
bne.s endl
newvals: tst.w d5 ;now: do the effects!!!
bne.s nonewper
move.w (a3),d5 ;no new period specified: get the old
nonewper: move.w d7,d4 ;channel number to d4
lsl.w #2,d4 ;and shift it to make it a longword index
lea audaddr,a1
movea.l 0(a1,d4.w),a1
move.w d5,ac_per(a1)
clr.w d5
move.b (a4),d5
move.w d5,ac_vol(a1)
endl: addq.l #2,a3 ;inc pointer to previous period value
addq.l #1,a4 ;and previous volume
addq.l #1,d7 ;increment channel number
cmp.w numtracks,d7 ;all channels done???
blt.w trloop1 ;not yet!!!
bsr _StartDMA ;turn on DMA
move.b _tamakappale+1551,d0 ;get the flags
btst #1,d0 ;is Topi's jumping on ???
beq.w exitint ;no
btst #2,d0 ;every 8th note ???
beq.s no8th
move.w #$0007,d0
and.w _soittorivi,d0 ;is this 8th note ??
bne.s no8th ;no...
tst.b animcnt
bne.s no8th
tst.w _soittotila
beq.s no8th
move.b #1,animcnt
no8th: tst.b animcnt
beq.s exitint
add.b #1,animpause ;Handles all animation
cmp.b #2,animpause
blt.s exitint
cmp.b #10,animcnt
bne.s nojumpend
clr.b animcnt
move.b #1,animpause
bra.s exitint
nojumpend: clr.w d0
move.b animcnt,d0
add.b #1,animcnt
lsl.w #2,d0
lea frame(pc),a1
move.l 0(a1,d0.w),_sprptr
tst.w _naytonpaivitys
beq.s exitint
sigjump: movea.l _maintsk,a1 ;and asks the main task to...
move.l _hyppymsk,d0 ;...SetPointer() !!!!!
jsr -$144(a6) ;Signal()
clr.b animpause
exitint: movem.l (sp)+,d2-d7/a2-a4
rts
_SetTempo: move.w d0,_tempo
cmp.b #10,d0 ;If tempo <= 10, use SoundTracker tempo
bhi.s calctempo
lea sttempo(pc),a1
lsl.w #1,d0
move.w 0(a1,d0.w),d1
bra.s pushtempo
calctempo: move.l #470000,d1
divu d0,d1
pushtempo: move.b d1,$bfe401 ;and set the CIA timer
lsr.w #8,d1
move.b d1,$bfe501
or.b #4,_specialupd
rts ; vv-- These values are the SoundTracker tempos (approx.)
sttempo: dc.w $0f00,2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
midifx: cmp.b #1,d6
bne.s nomidi01fx
lea prevmidichan,a1
lea prevpitchbend,a0
clr.w d1
move.b 0(a1,d7.w),d1 ;get previous midi channel
lsl.w #1,d1 ;UWORD index
tst.b d4 ;x100??
beq.s resetpbend
move.w 0(a0,d1.w),d0 ;get previous pitch bend
lsl.w #3,d4 ;multiply bend value by 8
add.w d4,d0
cmp.w #$3fff,d0
bls.s bendpitch
move.w #$3fff,d0
bendpitch: move.w d0,0(a0,d1.w) ;save current pitch bend
lsr.b #1,d1 ;back to UBYTE
or.b #$e0,d1
lea noteondata,a0
move.b d1,(a0) ;midi command & channel
move.b d0,1(a0) ;lower value
and.b #$7f,1(a0) ;clear bit 7
lsr.w #7,d0
and.b #$7f,d0 ;clr bit 7
move.b d0,2(a0) ;higher 7 bits
moveq.l #3,d0
bsr.w _AddMIDIData
bra.w endl
nomidi01fx: cmp.b #2,d6
bne.s nomidi02fx
lea prevmidichan,a1
lea prevpitchbend,a0
clr.w d1
move.b 0(a1,d7.w),d1
lsl.w #1,d1
tst.b d4
beq.s resetpbend ;x200??
move.w 0(a0,d1.w),d0
lsl.w #3,d4
sub.w d4,d0
bpl.s bendpitch ;not under 0
clr.w d0
bra.s bendpitch
nomidi02fx: cmp.b #$0f,d6
beq.w fx0f
cmp.b #$0e,d6
bne.w endl
bra.w fx0e
resetpbend: tst.b _counter
bne.w endl
move.w #$2000,d0
bra.s bendpitch
DoArpeggio: ; beginning note table in a1, note num returned in d4
move.b 0(a1,d7.w),d1 ;d1 = # of previous note played
move.b _counter,d0
tst.b d0
beq.s arpg03
cmp.b #3,d0
bne.s arpgn03
arpg03: and.b #$0f,d4 ;counter = 0 or 3: get last number
add.b d1,d4 ;add it to note number
rts
arpgn03: cmp.b #1,d0
beq.s arpg14
cmp.b #4,d0
bne.s arpgn14
arpg14: lsr.b #4,d4 ;counter = 1 or 4: get the first number
add.b d1,d4 ;add to prev. note
rts
arpgn14: move.b d1,d4 ;2 or 5: the previous note
rts
getinsdata: clr.l d2
move.w 4(a0),d0 ;Soitin-struct in a0, instr#<<1: d3
bne.s iff5or3oct ;note # in d1 (0 - ...)
move.l a0,d0
lea _periodit,a0
lsl.b #1,d1
move.w 0(a0,d1.w),d5 ;put period to d5
move.l d0,a0
addq.l #6,d0 ;Skip structure
move.l (a0),d1 ;length
lea _tamakappale+1316,a0
move.w 0(a0,d3.w),d2
move.w 64(a0,d3.w),d3
rts
iff5or3oct: movem.l a1/d6-d7,-(sp)
clr.l d7
move.w d1,d7
divu #12,d7 ;octave #
move.l d7,d5
swap d5 ;note number in this oct (0-11) is in d5
move.l (a0),d1
cmp.b #2,d0
bne.s no3oct
addq.l #6,d7
divu #7,d1 ;get length of the 1st octave
bra.s no5oct
no3oct: divu #31,d1 ;get length of the 1st octave (5 octaves)
no5oct: move.l d1,d0 ;d0 and d1 = length of the 1st oct
lea _tamakappale+1316,a1
move.w 0(a1,d3.w),d2
move.w 64(a1,d3.w),d3
clr.w d6
move.b shiftcnt(pc,d7.w),d6
lsl.w d6,d2
lsl.w d6,d3
lsl.w d6,d1
move.b mullencnt(pc,d7.w),d6
mulu d6,d0 ;offset of this oct from 1st oct
add.l a0,d0 ;add base address to offset
addq.l #6,d0 ;skip structure
lea _periodit,a1
add.b octstart(pc,d7.w),d5
lsl.b #1,d5
move.w 0(a1,d5.w),d5
movem.l (sp)+,a1/d6-d7
rts ;returns period in d5
shiftcnt: dc.b 4,3,2,1,1,0,2,2,1,1,0,0
mullencnt: dc.b 15,7,3,1,1,0,3,3,1,1,0,0
octstart: dc.b 12,12,12,12,24,24,0,12,12,24,24,36
xref _ciaaresource
xref _maintsk
_AudioInit: movem.l a6/d2,-(sp)
clr.l d2
movea.l 4,a6
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ alloc signal bit
addq.l #1,d2
st.l d0 ; -1
jsr -$14a(a6) ;AllocSignal()
tst.b d0
bmi.w initerr
move.b d0,sigbitnum
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ prepare IORequest
lea allocport(pc),a1
move.b d0,15(a1) ;set mp_SigBit
move.l _maintsk,16(a1) ;set mp_SigTask
lea reqlist(pc),a0
move.l a0,(a0) ;NEWLIST begins...
addq.l #4,(a0)
clr.l 4(a0)
move.l a0,8(a0) ;NEWLIST ends...
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ open audio.device
addq.l #1,d2
lea allocreq(pc),a1
lea audiodevname(pc),a0
clr.l d0
clr.l d1
movea.l 4,a6
jsr -$1bc(a6) ;OpenDevice()
tst.b d0
bne.s initerr
st.b audiodevopen
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ open ciaa.resource
addq.l #1,d2
clr.l d0
lea ciaaname(pc),a1
jsr -$1f2(a6) ;OpenResource()
tst.l d0
beq.s initerr
move.l d0,_ciaaresource
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ attach interrupt
addq.l #1,d2
move.l d0,a6
lea timerinterrupt(pc),a1
clr.l d0 ;Bit number 0: Timer A
jsr -$6(a6) ;AddICRVector
tst.l d0
bne.s initerr
and.b #%10000000,$bfee01
move.l #%10000001,d0
jsr -$12(a6) ;AbleICR()
st.b timeropen
clr.w _soittotila
clr.l d0
initret: movem.l (sp)+,a6/d2
rts
initerr: move.l d2,d0
bra.s initret
_AudioRem: move.l a6,-(sp)
tst.b timeropen
beq.s rem1
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ remove interrupt
move.l _ciaaresource,a6
lea timerinterrupt(pc),a1
clr.l d0 ;Bit number 0: Timer A
jsr -$c(a6) ;RemICRVector
;There is no CloseResource(). I'm not sure if I should use CloseLibrary()??
rem1: movea.l 4,a6
tst.b audiodevopen
beq.s rem2
move.w #$000f,$dff096 ;stop audio DMA
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ close audio.device
lea allocreq(pc),a1
jsr -$1c2(a6) ;CloseDevice()
rem2: clr.l d0
move.b sigbitnum,d0
bmi.s rem3
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ free signal bit
jsr -$150(a6) ;FreeSignal()
rem3: move.l (sp)+,a6
rts
_GetSerial: move.l a6,-(sp) ;Get serial port for MIDI
move.l 4,a6
clr.l d0
lea miscresname(pc),a1
jsr -$1f2(a6) ;OpenResource()
move.l d0,miscresbase
tst.l d0
beq.s gserror
move.l d0,a6
lea medname(pc),a1
clr.l d0 ;serial port
jsr -$6(a6) ;AllocMiscResource()
tst.l d0
bne.s gserror
st.b serportalloc
moveq.l #0,d0 ;TBE
lea serinterrupt(pc),a1
move.l 4,a6
jsr -$a2(a6) ;SetIntVector()
move.l d0,prevtbe
moveq.l #11,d0 ;RBF
lea rbfinterrupt(pc),a1
jsr -$a2(a6) ;SetIntVector()
move.l d0,prevrbf
move.w #$8001,$dff09a ;TBE on!!
move.w #114,$dff032 ;set baud rate (SERPER)
clr.l d0
retgs: move.l (sp)+,a6
rts
gserror: st d0
bra.s retgs
_FreeSerial: move.l a6,-(sp)
tst.l miscresbase
beq.s retfs
tst.b serportalloc
beq.s retfs
move.w #$0801,$dff09a ;disable RBF & TBE
movea.l prevtbe(pc),a1
moveq.l #0,d0
movea.l 4,a6
jsr -$a2(a6) ;SetIntVector()
movea.l prevrbf(pc),a1
moveq.l #11,d0
jsr -$a2(a6) ;SetIntVector()
movea.l miscresbase(pc),a6
clr.l d0 ;serial port
jsr -$c(a6) ;FreeMiscResource()
clr.b serportalloc
retfs: move.l (sp)+,a6
rts
prevtbe: dc.l 0
prevrbf: dc.l 0
xref _recmidi
xref _recmidimsk
RBFIntHandler: move.w $18(a0),d0 ;SERDATR
move.w #$0800,$9c(a0) ;clr intreq
btst #7,d0 ;status??
beq.s nostatus
move.b d0,(a1)
move.b #$1,3(a1)
rts
nostatus: clr.w d1
move.b 3(a1),d1
move.b d0,0(a1,d1.w)
addq.b #1,d1
cmp.b #3,d1
bge.s sigmidirec
move.b d1,3(a1)
rts
sigmidirec: move.b #$1,3(a1)
and.b #$f0,(a1)
cmp.b #$90,(a1)
bne.s nosrec
move.b 1(a1),_recmidi
movea.l _maintsk,a1
move.l _recmidimsk,d0
jsr -$144(a6) ;Signal()
nosrec: rts
recmidi: dc.b 0,0,0,0
SerIntHandler: move.w #1,$9c(a0) ;clear intreq bit
clr.l d0
move.b bytesinbuff(pc),d0
beq.s exsih ;buffer empty
move.w #$100,d1 ;Stop bit
move.b sendbuffer(pc),d1
move.w d1,$30(a0) ;SERDAT
move.w #$4000,$9a(a0) ;NO ONE may stop us!!!
addq.b #1,$126(a6)
lea sendbuffer(pc),a5
shiftdataloop: subq.b #1,d0 ;shift serial buffer 1 byte left
beq.s endshiftloop
move.b (a1)+,(a5)+ ;a1 = is_Data = sendbuffer + 1
bra.s shiftdataloop
endshiftloop: subq.b #1,bytesinbuff
subq.b #1,$126(a6)
bge.s exsih
move.w #$c000,$9a(a0)
exsih: rts
_AddMIDIData: tst.b serportalloc
beq.s retamd
movem.l d2/a6,-(sp)
movea.l 4,a6
move.w #$4000,$dff09a ;No interrupts...
addq.b #1,$126(a6)
clr.w d1
clr.b d2
move.b bytesinbuff(pc),d1
seq.b d2
add.b d0,d1
cmp.b #127,d1
bgt.s overflow ;sorry, can't do anything.
move.b d1,bytesinbuff
sub.b d0,d1
lea sendbuffer(pc,d1.w),a1
adddataloop: move.b (a0)+,(a1)+
subq.b #1,d0
bne.s adddataloop
overflow: subq.b #1,$126(a6)
bge.s nointena
move.w #$c000,$dff09a
nointena: tst.b d2
beq.s nonewtbe
move.w #$8001,$dff09c ;request TBE
nonewtbe: movem.l (sp)+,d2/a6
retamd: rts
sendbuffer: ds.b 128
miscresbase: dc.l 0
noteondata: dc.l 0
audiodevopen: dc.b 0
timeropen: dc.b 0
serportalloc: dc.b 0
bytesinbuff: dc.b 0
preschgdata: dc.b 0,0
pbendresdata: dc.b $e0,$00,$40 ;for fast pitch bend resetting
sigbitnum: dc.b -1
timerinterrupt: dc.w 0,0,0,0,0
dc.l timerintname,0,_IntHandler
serinterrupt: dc.w 0,0,0,0,0
dc.l serintname,sendbuffer+1,SerIntHandler
rbfinterrupt: dc.w 0,0,0,0,0
dc.l rbfintname,recmidi,RBFIntHandler
allocport: dc.l 0,0 ;succ, pred
dc.b 4,0 ;NT_MSGPORT
dc.l 0 ;name
dc.b 0,0 ;flags = PA_SIGNAL
dc.l 0 ;task
reqlist: dc.l 0,0,0 ;list head, tail and tailpred
dc.b 5,0
allocreq: dc.l 0,0
dc.b 5,127 ;NT_MESSAGE, maximum priority (127)
dc.l 0,allocport ;name, replyport
dc.w 68 ;length
dc.l 0 ;io_Device
dc.l 0 ;io_Unit
dc.w 0 ;io_Command
dc.b 0,0 ;io_Flags, io_Error
dc.w 0 ;ioa_AllocKey
dc.l sttempo ;ioa_Data
dc.l 1 ;ioa_Length
dc.w 0,0,0 ;ioa_Period, Volume, Cycles
dc.w 0,0,0,0,0,0,0,0,0,0 ;ioa_WriteMsg
ciaaname: dc.b 'ciaa.resource',0
timerintname: dc.b 'MEDTimerInterrupt',0
serintname: dc.b 'MEDSerialInterrupt',0
rbfintname: dc.b 'MEDSerialRBFInt',0
audiodevname: dc.b 'audio.device',0
miscresname: dc.b 'misc.resource',0
medname: dc.b 'MED',0 ;yeah, our name
end